package com.wsoft.hr.pm.service.impl.sys;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wsoft.constant.redis.HrPmRedisKeyConstant;
import com.wsoft.constant.redis.RedisKeyConstant;
import com.wsoft.core.annotation.GetRedisCache;
import com.wsoft.core.annotation.InitRedisCache;
import com.wsoft.core.cmd.DataPermSourceService;
import com.wsoft.core.exception.Asserts;
import com.wsoft.core.service.CommonOrgService;
import com.wsoft.core.utils.SqlAuthDisableHolder;
import com.wsoft.core.vo.OrganizationVO;
import com.wsoft.hr.pm.entity.sys.HrOrganizationEntity;
import com.wsoft.hr.pm.manager.sys.HrOrganizationManager;
import com.wsoft.hr.pm.mapper.HrOrganizationMapper;
import com.wsoft.hr.pm.query.sys.HrOrgInsertQuery;
import com.wsoft.hr.pm.query.sys.HrOrgListQuery;
import com.wsoft.hr.pm.query.sys.HrOrgUpdateQuery;
import com.wsoft.hr.pm.query.sys.OrgInitQuery;
import com.wsoft.hr.pm.service.sys.IHrOrganizationService;
import com.wsoft.hr.pm.vo.sys.HrOrganizationVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhanggukai
 * @since 2025年02月17日 15:27:01
 */
@Service(value = "hrOrganizationService")
public class HrOrganizationServiceImpl extends ServiceImpl<HrOrganizationMapper, HrOrganizationEntity> implements IHrOrganizationService , DataPermSourceService {

    @Resource
    private CommonOrgService commonOrgService;

    @Resource
    private HrOrganizationManager hrOrganizationManager;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @InitRedisCache(type =  HrPmRedisKeyConstant.HR_ALL_ORG,
            value = RedisKeyConstant.REDIS_NULL)
    public synchronized void initPmOrganization(OrgInitQuery query) {
        List<OrganizationVO> all = commonOrgService.getOrganizationAll();
        List<OrganizationVO> list = new ArrayList<>();
        // 获取包含子级组织数据
        if (query.isHasChild()) {
            query.getIds().forEach(parentId -> {
                List<OrganizationVO> orgList = commonOrgService.getChildOrg(parentId);
                list.addAll(orgList);
            });
            list.stream()
                    // 去重复
                    .collect(Collectors.toMap(OrganizationVO::getId, p -> p, (p1, p2) -> p1))
                    .values()
                    .stream()
                    // sort升序
                    .sorted(Comparator.comparingInt(OrganizationVO::getSort))
                    .collect(Collectors.toList());
        }
        // 不包含子级组织数据
        else {
            query.getIds().forEach(parentId -> {
                OrganizationVO orgInfo = commonOrgService.getOrgInfo(parentId);
                list.add(orgInfo);
            });
        }
        //查询数据库 是否为初始化数据
        List<HrOrganizationEntity> entityList = listAllHrOrgWithCache();
        if(entityList.isEmpty()){
            //查询根组织数据
            if (!list.isEmpty()) {
                String sub = list.get(0).getAuthCode().substring(0, 3);
                OrganizationVO organizationVO = all.stream().filter(e -> {
                    return e.getAuthCode().equals(sub);
                }).findFirst().get();
                //初始化根组织数据
                HrOrgInsertQuery insert = Convert.convert(HrOrgInsertQuery.class, organizationVO);
                insert.setAddChild(false);
                insert(insert);
            }
        }

        //新增绩效组织表
        List<OrganizationVO> sorted = list.stream().sorted(Comparator.comparing(OrganizationVO::getAuthCode))
                .collect(Collectors.toList());
        for (OrganizationVO org : sorted){
            HrOrgInsertQuery convert = Convert.convert(HrOrgInsertQuery.class, org);
            if (org.getPaId()==0L){
                continue;
            }
            //根据编码查询出父id
            OrganizationVO organizationVO = all.stream().filter(e -> e.getId().equals(org.getPaId())).findFirst().get();
            List<HrOrganizationEntity> orgByCode = hrOrganizationManager.getOrgByCode(null,organizationVO.getCode());
            if (!orgByCode.isEmpty()){
                convert.setPaId(orgByCode.get(0).getId());
            }
            else {
                List<HrOrganizationEntity> orgByPaId = hrOrganizationManager.getOrgByPaId(0L);
                if (!orgByPaId.isEmpty()){
                    convert.setPaId(orgByPaId.get(0).getId());
                }
            }
            convert.setAddChild(false);
            insert(convert);
        }
        }


    @Override
    @InitRedisCache(type =  HrPmRedisKeyConstant.HR_ALL_ORG,
            value = RedisKeyConstant.REDIS_NULL)
    public boolean insert(HrOrgInsertQuery query) {
        HrOrganizationEntity entity = Convert.convert(HrOrganizationEntity.class, query);
        List<HrOrganizationEntity> orgByCode = hrOrganizationManager.getOrgByCode(null,query.getCode());
        if (orgByCode.size()>0){
            Asserts.fail("[sys.code.exist]");
        }
        List<HrOrganizationEntity> orgByPaId = hrOrganizationManager.getOrgByPaId(0L);
        if (!orgByPaId.isEmpty()){
            if (orgByPaId.get(0).getId().equals(entity.getPaId())&&query.getAddChild()){
                Asserts.fail("[hr.org.add.error]");
            }
        }

        //更新权限组织编码
        setOrgCode(entity);
        boolean b = save(entity);
        if (b){
            HrOrganizationEntity update = new HrOrganizationEntity();
            update.setId(entity.getId());
            update.setHrOrgId(entity.getId());
            return updateById(update);
        }
        return false;
    }

    @Override
    @InitRedisCache(types = {HrPmRedisKeyConstant.HR_ORG, HrPmRedisKeyConstant.HR_ALL_ORG },
            values = {"id",  RedisKeyConstant.REDIS_NULL})
    public boolean update(HrOrgUpdateQuery query) {
        HrOrganizationEntity entity = Convert.convert(HrOrganizationEntity.class, query);
        List<HrOrganizationEntity> orgByCode = hrOrganizationManager.getOrgByCode(query.getId(),query.getCode());
        if (!orgByCode.isEmpty()){
            Asserts.fail("[sys.code.exist]");
        }
//        List<HrOrganizationEntity> orgByPaId = hrOrganizationManager.getOrgByPaId(0L);
//        if (!orgByPaId.isEmpty()){
//            if (orgByPaId.get(0).getId().equals(entity.getPaId())){
//                Asserts.fail("[hr.org.add.error]");
//            }
//        }
        return updateById(entity);
    }

    @Override
    @GetRedisCache(type = HrPmRedisKeyConstant.HR_ORG,
            value = RedisKeyConstant.REDIS_SELF)
    public HrOrganizationEntity getOrgById(Long id) {
        return getById(id);
    }

    @Override
    @InitRedisCache(types = {HrPmRedisKeyConstant.HR_ORG, HrPmRedisKeyConstant.HR_ALL_ORG },
            values = {RedisKeyConstant.REDIS_SELF,  RedisKeyConstant.REDIS_NULL})
    public boolean delete(Long id) {
        List<HrOrganizationEntity> orgByPaId = hrOrganizationManager.getOrgByPaId(id);
        if (!orgByPaId.isEmpty()){
            Asserts.fail("[sys.org.del.sub]");
        }
        return removeById(id);
    }

    @Override
    public List<HrOrganizationEntity> getOrgList(HrOrgListQuery listQuery) {
        QueryWrapper<HrOrganizationEntity> query = new QueryWrapper<>();
        //父id
        SqlAuthDisableHolder.open();
        QueryWrapper<HrOrganizationEntity> paQuery = new QueryWrapper<>();
        paQuery.lambda().eq(HrOrganizationEntity::getPaId,0L);
        List<HrOrganizationEntity> list = list(paQuery);
        SqlAuthDisableHolder.close();
        if (CollUtil.isNotEmpty(list)){
            if (list.get(0).getId()!=null){
                query.lambda().eq(HrOrganizationEntity::getPaId,list.get(0).getId());
            }
        }
        //编码
        if (StrUtil.isNotBlank(listQuery.getCode())){
            query.lambda().eq(HrOrganizationEntity::getCode,listQuery.getCode());
        }
        //全称
        if (StrUtil.isNotBlank(listQuery.getName())){
            query.lambda().eq(HrOrganizationEntity::getName,listQuery.getName());
        }
        //类型
        if (StrUtil.isNotBlank(listQuery.getType())){
            query.lambda().eq(HrOrganizationEntity::getType,listQuery.getType());
        }
        query.lambda().orderByAsc(HrOrganizationEntity::getSort);
        return list(query);
    }

    @Override
    public List<HrOrganizationEntity> listAllHrOrgWithCache() {
        return hrOrganizationManager.listAllHrOrgWithCache();
    }

    @Override
    public List<HrOrganizationVO> selectOrgListTree() {
        List<HrOrganizationEntity> list = list();
        List<HrOrganizationVO> collect = list.stream().map(e -> Convert.convert(HrOrganizationVO.class, e)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(list)) {
            return buildHrOrganizationVO(collect);
        }
        return CollUtil.newArrayList();
    }

    @Override
    public List<HrOrganizationVO> getChildOrg(Long orgId , boolean haveOwn) {
        List<HrOrganizationEntity> list = listAllHrOrgWithCache();
        HrOrganizationEntity org = getOrgById(orgId);
        List<HrOrganizationVO> result = list.stream().filter(e -> e.getAuthCode().startsWith(org.getAuthCode()))
                .map(item -> Convert.convert(HrOrganizationVO.class, item)).collect(Collectors.toList());
        if (!haveOwn){
            return result.stream().filter(e -> !e.getId().equals(org.getId())).collect(Collectors.toList());
        }
        return result;
    }

    private void setOrgCode(HrOrganizationEntity entity) {
        String code = "";
        // 获取父级代码
        HrOrganizationEntity parent = getOrgById(entity.getPaId());
        QueryWrapper<HrOrganizationEntity> query = new QueryWrapper<>();
        //找出该节点下最大编码
        if (parent != null && StrUtil.isNotBlank(parent.getCode())) {
            query.lambda().eq(HrOrganizationEntity::getPaId,entity.getPaId());
        }
        else {
            query.lambda().eq(HrOrganizationEntity::getPaId,0L);
        }
        List<HrOrganizationEntity> list = list(query);
        List<String> collect = list.stream().map(HrOrganizationEntity::getAuthCode).collect(Collectors.toList());
        List<String > result= new ArrayList<>();
        collect.forEach(e->{
            result.add(e.substring(e.length()-3));
        });

        int maxOrderNumber = result.stream()
                .mapToInt(Integer::parseInt)
                .max()
                .orElse(0);

        // 拼接当前组织编码
        int nextOrderNumber = maxOrderNumber + 1;
        if (maxOrderNumber==0){
            code="001";
        }
        // 将整数转换回指定格式的字符串（如果需要保持前导零
        else {
            code = String.format("%03d", nextOrderNumber);
        }
        if (parent==null){
            entity.setAuthCode(code);
        }else{
            entity.setAuthCode(parent.getAuthCode()+code);
        }

    }
    private List<HrOrganizationVO> buildHrOrganizationVO(List<HrOrganizationVO> vos) {
        List<HrOrganizationVO> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<>();
        for (HrOrganizationVO vo : vos) {
            tempList.add(vo.getId());
        }
        for (HrOrganizationVO vo : vos) {
            if (!tempList.contains(vo.getPaId())) {
                recursionFn(vos, vo);
                returnList.add(vo);
            }
        }
        if (returnList.isEmpty()) {
            returnList = vos;
        }
        return returnList;
    }

    private void recursionFn(List<HrOrganizationVO> vos, HrOrganizationVO vo) {
        List<HrOrganizationVO> childList = getChildList(vos, vo);
        vo.setChildren(childList);
        for (HrOrganizationVO child : childList) {
            if (hasChild(vos, child)) {
                recursionFn(vos, child);
            }
        }
    }
    /**
     * 获取子节点列表
     */
    private List<HrOrganizationVO> getChildList(List<HrOrganizationVO> vos, HrOrganizationVO vo) {
        List<HrOrganizationVO> childList = new ArrayList<>();
        for (HrOrganizationVO n : vos) {
            if (n.getPaId() != null && Objects.equals(n.getPaId(), vo.getId())) {
                childList.add(n);
            }
        }
        return childList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<HrOrganizationVO> vos, HrOrganizationVO vo) {
        return getChildList(vos, vo).size() > 0;
    }

    @Override
    public List<Object> loadDataSource() {
        List<HrOrganizationEntity> entityList = listAllHrOrgWithCache();
        return entityList.stream().map(e->Convert.convert(HrOrganizationEntity.class,e)).collect(Collectors.toList());
        }
}

